# -*- encoding:utf-8 -*-
# @Time: 2022/11/23 20:21
# @Author : moran
# @Email: moran@maqu.com
# @File: serializers.py
# @Software: PyCharm
from datetime import datetime
from decimal import Decimal
from random import randint

from django.db import transaction
from rest_framework import serializers
from rest_framework.serializers import SerializerMethodField
from rest_framework.serializers import ModelSerializer

from users.models import Address
from .models import *


class ClassificationSerializer(ModelSerializer):
    class Meta:
        model = Classification
        fields = ['id', 'name']


class ParentClassificationSerializer(ModelSerializer):
    classification_set = ClassificationSerializer(many=True, read_only=True)

    class Meta:
        model = Classification
        fields = ['id', 'name', 'classification_set', 'parent']

    extra_kwargs = {
        'parent': {'write_only': True}
    }


class CommodityImgSerializer(ModelSerializer):
    class Meta:
        model = CommodityImg
        fields = ['src']


class CommoditySerializer(ModelSerializer):
    classification1_name = serializers.CharField(source='classification1.name', read_only=True)
    classification2_name = serializers.CharField(source='classification2.name', read_only=True)
    commodityimg_set = CommodityImgSerializer(many=True, read_only=True)

    class Meta:
        model = Commodity
        exclude = ['is_delete']


class ShoppingCartSerializer(ModelSerializer):
    commodityDetail = SerializerMethodField()

    class Meta:
        model = ShoppingCart
        fields = '__all__'

    def get_commodityDetail(self, shoppingcart):
        return CommoditySerializer(shoppingcart.commodity).data


class OrderSerializer(ModelSerializer):
    cart = serializers.ListField(write_only=True)  # 获得前端购物车传入过来要结算的商品

    class Meta:
        model = Order
        fields = '__all__'
        read_only_fields = ['order_id', 'total_count', 'total_amount', 'status', 'user']

    def create(self, validated_data):
        # 自定义创建订单
        # 生成订单编号 唯一 标识：2022112521242000000124
        user = self.context['request'].user
        order_id = datetime.now().strftime('%Y%m%d%H%M%S')+'%06d%02d' % (user.id, randint(1, 99))

        # 获取前端传入的支付方法与收货地址
        pay_method = validated_data.get('pay_method')
        try:
            address = Address.objects.get(id=validated_data.get('address'))
        except Address.DoesNotExist:
            raise serializers.ValidationError('address error')
        # 湖南省 长沙市 岳麓区 麓谷新长海中心B3栋303 [阿斗收] 15566668888
        address_res = f'{address.province.name} {address.city.name} {address.district.name} {address.place} [{address.receiver} 收] {address.mobile}'
        with transaction.atomic():
            # 开启事务，在with缩进里面的代码执行完毕之后会自动关闭事务
            # 事务里面的代码是在同一个原子中
            save_point = transaction.savepoint()  # 创建保存点
            try:
                # 创建订单信息
                order = Order.objects.create(
                    order_id=order_id,
                    total_count=0,
                    total_amount=Decimal('0.00'),
                    pay_method=pay_method,
                    address=address_res,
                    status=1 if pay_method == 1 else 2,  # 支付宝支付，状态为待支付，货到付款，待收货
                    user=user,
                )
                # 获取购物车中要结算的商品
                carts = validated_data.get('cart')  # 要结算的商品id列表
                for cart_id in carts:
                    while True:
                        try:
                            cart = ShoppingCart.objects.get(id=cart_id)
                        except ShoppingCart.DoesNotExist:
                            raise serializers.ValidationError('购物信息不存在')
                        # 得到购物车中的商品信息，库存数量，销量
                        commodity = cart.commodity
                        print(commodity)
                        # 获得原本的库存和销量
                        origin_stock = commodity.stock
                        origin_sales = commodity.sales
                        # 核算 购买的数量是否超过库存
                        if cart.number > origin_stock:
                            raise serializers.ValidationError('库存不足')
                        # 库存与销量操作：库存减少 销量增加
                        new_stock = origin_stock - cart.number
                        new_sales = origin_sales + cart.number
                        # 更新商品信息
                        res = Commodity.objects.filter(id=commodity.id, stock=origin_stock).update(stock=new_stock, sales=new_sales)
                        if not res:
                            continue
                        # 创建订单对应的商品数据
                        OrderGoods.objects.create(
                            number=cart.number,
                            price=commodity.price,
                            order=order,
                            commodity=commodity
                        )
                        # 更新订单表
                        order.total_count += cart.number
                        order.total_amount += (cart.number * commodity.price)
                        break
                # 保存订单信息
                order.save()
                # 清除购物车
                ShoppingCart.objects.filter(id__in=carts).delete()
            except Exception as e:
                transaction.savepoint_rollback(save_point)  # 当出现异常进行事务回滚
                raise serializers.ValidationError(e)  # 结束返回响应给客户端对应的错误信息
            else:
                transaction.savepoint_commit(save_point)  # 当没有异常时进行事务提交
        # 返回
        return order


class PaymentSerializer(ModelSerializer):
    class Meta:
        model = Payment
        fields = '__all__'
